/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package server;

import common.XmlConstants;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;


/*
 * This file is part of shared-drawing.
 * shared-drawing is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option )
 * any later version. shared-drawing is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * You should have received a copy of the GNU General Public License along with 
 * shared-drawing. If not, seehttp://www.gnu.org/licenses/.
 */

/**
 *
 * @author mika
 */
class XmlReaderServer implements ContentHandler {
    
    private WorkGroupThread work_group;
    private ClientThread client_thread;
    private String user_id;
    private Locator locator;
    private Document to_send;
    private boolean create_page;
    private boolean valid_action;
    private boolean is_an_update;
    private Integer asker;
    private Element currentShape;
    Element users;
    Element pages;
    Element viewers;
    Element root;
    Element drawing;
    Element page;

    XmlReaderServer(WorkGroupThread work_group, ClientThread client, String id) {
        this.work_group = work_group;
        client_thread = client;
        to_send = new Document();
        user_id = id;
        valid_action = true;
        is_an_update = false;
        asker = 0;
        users = null;
        pages = null;
        viewers = null;
        currentShape = null;
        root = null;
        drawing = null;
        page = null;
    }

    @Override
    public void startElement(String nameSpaceURI, String localName, String rawName, Attributes attributes) throws SAXException
    {
        //switch root element
        if(XmlConstants.createDrawing.equals(localName))
        {
            drawing = new Element(XmlConstants.createDrawing);
            drawing.setAttribute(XmlConstants.pageId, attributes.getValue(XmlConstants.pageId));
            drawing.setAttribute(XmlConstants.drawingId, work_group.getNextDrawingId());
            drawing.setAttribute(XmlConstants.emitterId, user_id);
            if(is_an_update == true)
            {
                page.addContent(drawing);
            }
            else if(create_page)
            {
                root.addContent(drawing);
            }
            else
            {
                to_send.addContent(drawing);
            }
        }
        else if(XmlConstants.joinWorkgroup.equals(localName))
        {
            if(!is_an_update)
            {
                valid_action = false;
            }
            else
            {
                root = new Element(XmlConstants.joinWorkgroup);
                root.setAttribute(XmlConstants.emitterId, 
                        attributes.getValue(XmlConstants.emitterId));
                root.setAttribute(XmlConstants.emitterNickName, 
                        attributes.getValue(XmlConstants.emitterNickName));
                users.addContent(root);
            }
        }
        else if(XmlConstants.leaveWorkgroup.equals(localName))
        {
            root = new Element(XmlConstants.leaveWorkgroup);
            root.setAttribute(XmlConstants.emitterId, user_id);
            to_send.addContent(root);
            client_thread.leaveWorkGroup();
        }
        else if(XmlConstants.createPage.equals(localName))
        {
            root = new Element(XmlConstants.createPage);
            root.setAttribute(XmlConstants.pageName, attributes.getValue(XmlConstants.pageName));
            
            root.setAttribute(XmlConstants.emitterId, user_id);
            if(is_an_update)
            {
                root.setAttribute(XmlConstants.creatorId, attributes.getValue(XmlConstants.creatorId));
                root.setAttribute(XmlConstants.pageId, attributes.getValue(XmlConstants.pageOld));
                page = root;
                pages.addContent(root);
            }
            else
            {
                root.setAttribute(XmlConstants.pageId, work_group.getNextPageId());
                root.setAttribute(XmlConstants.pageOld, attributes.getValue(XmlConstants.pageOld));
                create_page = true;
                to_send.addContent(root);
            }
        }
        else if(XmlConstants.openPage.equals(localName))
        {
            root = new Element(XmlConstants.openPage);
            root.setAttribute(XmlConstants.pageId, attributes.getValue(XmlConstants.pageId));
            root.setAttribute(XmlConstants.viewerId, attributes.getValue(XmlConstants.viewerId));
            root.setAttribute(XmlConstants.emitterId, user_id);
            if(is_an_update == true)
            {
                viewers.addContent(root);
            }
            else
            {
                to_send.addContent(root);
            }
        }
        else if(XmlConstants.closePage.equals(localName))
        {
                root = new Element(XmlConstants.closePage);
                root.setAttribute(XmlConstants.pageId, attributes.getValue(XmlConstants.pageId));
                root.setAttribute(XmlConstants.emitterId, user_id);
                to_send.addContent(root);
        }
        else if(XmlConstants.chat.equals(localName))
        {
            root = new Element(XmlConstants.chat);
            root.setAttribute(XmlConstants.message, attributes.getValue(XmlConstants.message));
            root.setAttribute(XmlConstants.emitterId, user_id);
            to_send.addContent(root);
        }
        else if(XmlConstants.shapeContent.equals(localName))
        {
            Element child = new Element(XmlConstants.shapeContent);
            String next = work_group.getNextShapeContentId();
            child.setAttribute(XmlConstants.shapeContentId, next);
            for(int index = 0;index<attributes.getLength();index++)
            {
                child.setAttribute(attributes.getLocalName(index), 
                                    attributes.getValue(index));
            }
            drawing.addContent(child);
            currentShape = child;
        }
        else if(XmlConstants.wgContent.equals(localName))
        {
            Element child = new Element(XmlConstants.wgContent);
            for(int index = 0;index<attributes.getLength();index++)
            {
                child.setAttribute(attributes.getLocalName(index), 
                                    attributes.getValue(index));
            }
            currentShape.addContent(child);
        }
        else if(XmlConstants.askUpToDate.equals(localName))
        {
            asker = Integer.parseInt(attributes.getValue(XmlConstants.emitterId));
            System.out.println("asker : " + asker);
            is_an_update = true;
            valid_action = true;
        }
        else if(XmlConstants.users.equals(localName))
        {
            if(is_an_update)
            {
                users = new Element(XmlConstants.users);
                work_group.getClient(asker).bufferize(new Document(users));
            }
        }
        else if(XmlConstants.pageCollection.equals(localName))
        {
            pages = new Element(XmlConstants.pageCollection);
            if(is_an_update)
            {
                work_group.getClient(asker).bufferize(new Document(pages));
            }
            //else discard
        }
        else if(XmlConstants.viewers.equals(localName))
        {
            if(is_an_update)
            {
                viewers = new Element(XmlConstants.viewers);
                work_group.getClient(asker).bufferize(new Document(viewers));
            }
            //else discard
        }
        else if(XmlConstants.undone.equals(localName))
        {
            //ignore
        }
        else 
        {
            System.out.println("Invalid message received : "+localName);
            valid_action = false;
        }
    }
    
    @Override
    public void endElement(String nameSpaceURI, String localName, String rawName) throws SAXException{
    }
    
    @Override
    public void startDocument() throws SAXException {   
        System.out.println("START DOCUMENT");
        to_send.removeContent();
        create_page = false;
        valid_action = true;
        is_an_update = false;
        asker = 0;
        currentShape = null;
        drawing = null;
        root = null;
        users = null;
        pages = null;
        viewers = null;
        page = null;
    }
    
    @Override
    public void setDocumentLocator(Locator value) {
        locator =  value;
    }

    @Override
    public void endDocument() throws SAXException { 
        if(valid_action)
        {
            if(is_an_update == true)
            {
                work_group.getClient(asker).makeUpToDate();
            }
            else
            {
                try {
                    work_group.addToQueue(to_send);
                } catch (InterruptedException ex) {
                    Logger.getLogger(XmlReaderServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
    
    @Override
    public void startPrefixMapping(String prefix, String URI) throws SAXException{
    }
    @Override
    public void endPrefixMapping(String prefix) throws SAXException{
    }
    @Override
    public void characters(char[] ch, int start, int end) throws SAXException{   
    }
    @Override
    public void ignorableWhitespace(char[] ch, int start, int end) throws SAXException{
    }
    @Override
    public void processingInstruction(String target, String data) throws SAXException{  
    }
    @Override
    public void skippedEntity(String arg0) throws SAXException{    
    }

}
